package com.nuoniu.sibanyun.utils;


import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayUtil;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.crm.CrmGoodsOrder;
import com.nuoniu.sibanyun.entity.expenses.ExpensesPaymentOrder;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信工具类
 * @author 小啊刚
 * @date 2020-08-22
 */
public class WeXinUtils {

    /** 微信公众号appId*/
    private static String APP_ID = "wx79de46406f734a22";
    /** 微信公众号秘钥*/
    private static String SECRET = "e4d3a9319279973cc1d98e064b2345fb";
    /** 商户号*/
    private static String MCH_ID = "1559877651";
    /** 商户秘钥*/
    private static String MCH_KEY = "e4d3a9319279973cc1d98e064b2345fb";
    /** 回调地址*/
    private static String NOTIFY_URL = "https://api.sibanyun.com/auth/wxPay/resultNotify";
    /** 统一下单接口*/
    private static String API_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /** 网页授权地址*/
    public final static String GetPageAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APP_ID + "&secret=" + SECRET;
    /** 网页授权接口*/
    public final static String GetPageAccessTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

    /**
     * 获取微信网业授权token 有效时间:两小时
     * @author 小啊刚
     * @date 2020-08-22
     */
    public static String getAccessToken() {
        String accessToken = null;
        try {
            String json = HttpClientUtil.sendGet(GetPageAccessTokenUrl);
            System.out.println("access_token" + json);
            Map data = JSONObject.parseObject(json);
            accessToken = data.get("access_token").toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return accessToken;
    }

    /**
     * 微信参数签名
     * @author 小啊刚
     * @date 2020-08-22
     */
    public static Map JsapiTicket(String accessToken, String url) {
        String requestUrl = GetPageAccessTicketUrl.replace("ACCESS_TOKEN", accessToken);
        Map<String,String> map = new HashMap();
        try {
            String json = HttpClientUtil.sendGet(requestUrl);
            System.out.println("ticket" + json);
            Map data = JSONObject.parseObject(json);
            String ticket = data.get("ticket").toString();
            String nonceStr = StringUtils.getRandomStr(6);//随机字符串
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
            String str = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + "https://m.sibanyun.com/views/personal/userShare";
            String signature = encode(str);
            map.put("timestamp",timestamp);
            map.put("accessToken",accessToken);
            map.put("ticket",ticket);
            map.put("noncestr",nonceStr);
            map.put("signature",signature);
            map.put("appId", APP_ID);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 生成微信支付二维码地址
     * @author 小啊刚
     * @date 2020-08-21
     */
    public Map createNative(CrmGoodsOrder order){
        long totalFee = order.getSalePrice().multiply(new BigDecimal(100)).setScale( 0, BigDecimal.ROUND_UP ).longValue();
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("appid", APP_ID);
        hashMap.put("mch_id", MCH_ID);
        hashMap.put("nonce_str", WXPayUtil.generateNonceStr());
        hashMap.put("body", order.getGoodsName());
        hashMap.put("out_trade_no", order.getId().toString());
        hashMap.put("total_fee", String.valueOf(totalFee));
        hashMap.put("notify_url", NOTIFY_URL);
        hashMap.put("spbill_create_ip", "127.0.0.1");
        hashMap.put("trade_type", "NATIVE");
        hashMap.put("product_id", order.getGoodsId().toString());

        try {
            // 将参数转成xml发送
            String xmlParam = WXPayUtil.generateSignedXml(hashMap, MCH_KEY);
            // 创建https请求，调用统一支付接口
            HttpClient httpClient = new HttpClient(API_URL);
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlParam);
            httpClient.post();
            // 获取调用结果
            String content = httpClient.getContent();
            Map<String, String> stringStringMap = WXPayUtil.xmlToMap(content);
            Map map = new HashMap<>();
            map.put("code_url", stringStringMap.get("code_url"));
            map.put("total_fee", order.getSalePrice());
            map.put("out_trade_no", order.getOrderNo());
            return map;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成微信支付二维码地址
     * @author 小啊刚
     * @date 2020-08-21
     */
    public Map createNativeFormPayOrder(ExpensesPaymentOrder paymentOrder){
        long totalFee = paymentOrder.getPaymentAmount().multiply(new BigDecimal(100)).setScale( 0, BigDecimal.ROUND_UP ).longValue();
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("appid", APP_ID);
        hashMap.put("mch_id", MCH_ID);
        hashMap.put("nonce_str", WXPayUtil.generateNonceStr());
        hashMap.put("body", "");
        hashMap.put("out_trade_no", paymentOrder.getOrderNo());
        hashMap.put("total_fee", String.valueOf(totalFee));
        hashMap.put("notify_url", NOTIFY_URL);
        hashMap.put("spbill_create_ip", "127.0.0.1");
        hashMap.put("trade_type", "NATIVE");
        hashMap.put("product_id", paymentOrder.getId().toString());

        try {
            // 将参数转成xml发送
            String xmlParam = WXPayUtil.generateSignedXml(hashMap, MCH_KEY);
            // 创建https请求，调用统一支付接口
            HttpClient httpClient = new HttpClient(API_URL);
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlParam);
            httpClient.post();
            // 获取调用结果
            String content = httpClient.getContent();
            Map<String, String> stringStringMap = WXPayUtil.xmlToMap(content);
            Map map = new HashMap<>();
            map.put("code_url", stringStringMap.get("code_url"));
            map.put("total_fee", paymentOrder.getPaymentAmount());
            map.put("out_trade_no", paymentOrder.getOrderNo());
            return map;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 微信通知结果解析
     * @author 小啊刚
     * @date 2020-08-22
     */
    public static Map<String, String> resultNotify(String notifyData) throws Exception {
        Boolean flag = WXPayUtil.isSignatureValid(notifyData, MCH_KEY);
        if(flag) {
            Map<String, String> data = WXPayUtil.xmlToMap(notifyData);
            return data;
        }
        return null;
    }
    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        getAccessToken();
    }

}
